#include <iostream>

template <typename T>
struct Field {};

template <class T>
struct my_wrapper {
	inline static T value;
};

template <typename T, auto... field>
struct private_visitor {
  friend inline constexpr auto get_private_ptrs(const my_wrapper<T>&) {
    constexpr auto tp = std::make_tuple(field...);
    return tp;
  }
};

#define REFL_PRIVATE(STRUCT, ...)                                         \
  inline constexpr auto get_private_ptrs(const my_wrapper<STRUCT> &t);      \
  template struct private_visitor<STRUCT, ##__VA_ARGS__>;

struct Dog
{
	bool m_male;
};

struct Person
{
	bool m_male;
	Field<std::string> m_name;
	Field<int> m_age;
};

class PersonPrivate {
	Field<std::string> m_name;
	Field<int> m_age;
	bool m_male;
};
REFL_PRIVATE(PersonPrivate, &PersonPrivate::m_name, &PersonPrivate::m_age, &PersonPrivate::m_male)

struct AnyType {
	template <typename T>
	operator T();
};

template <typename T>
consteval size_t countMember(auto&&... Args) {
	if constexpr (!requires { T{ Args... }; }) {
		return sizeof...(Args) - 1;
	}
	else {
		return countMember<T>(Args..., AnyType{});
	}
}

template <typename T>
constexpr size_t member_count_v = countMember<T>();

template <class T>
inline constexpr T& get_global_object() noexcept {
	return my_wrapper<T>::value;
}

template <typename T>
struct Is_Field : std::false_type {
};

template <typename T>
struct Is_Field<Field<T>> : std::true_type {};

template <typename Tuple>
constexpr bool check_field(const Tuple& tuple) {
	bool found = false;

	std::apply([&](const auto&... args) {
		((found = found || Is_Field<std::decay_t<decltype(args)>>()), ...);
		}, tuple);

	return found;
}

template <auto ptr>
void f() {
#if defined(__GNUC__)
	constexpr std::string_view func_name = __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
	constexpr std::string_view func_name = __FUNCSIG__;
#endif
	std::cout << func_name << std::endl;
}

template <typename T, std::size_t n>
struct ReflectHelper{};

#define RFL_STRUCT(n, ...)                                                      \
template <class T>                                                              \
struct ReflectHelper<T, n> {												    \
	static constexpr auto reflectFieldImpl() {									\
		auto& [__VA_ARGS__] = get_global_object<T>();                           \
		auto ref_tup = std::tie(__VA_ARGS__);                                   \
		return check_field(ref_tup);                                            \
	}																		    \
}

RFL_STRUCT(1, f0);
RFL_STRUCT(2, f0, f1);
RFL_STRUCT(3, f0, f1, f2);
RFL_STRUCT(4, f0, f1, f2, f3);
RFL_STRUCT(5, f0, f1, f2, f3, f4);

template <auto ptr>
inline constexpr std::string_view get_member_name() {
#if defined(__GNUC__)
  constexpr std::string_view func_name = __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
  constexpr std::string_view func_name = __FUNCSIG__;
#endif
  return func_name;
}

template <auto MemberPtr>
struct MemberPointerTraits;

template <typename T, typename C, T C::*MemberPtr>
struct MemberPointerTraits<MemberPtr> {
    using type = T;
    using class_type = C;
};

template <auto MemberPtr>
using member_value_v = typename MemberPointerTraits<MemberPtr>::type;

template <typename T>
concept IsAggregate = std::is_aggregate_v<T>;

template <typename T>
struct ReflectField {
    static constexpr bool reflect() {
        constexpr auto tp = get_private_ptrs(my_wrapper<T>{});
        constexpr size_t N = std::tuple_size_v<decltype(tp)>;
        bool found = false;

        [&]<size_t... Is>(std::index_sequence<Is...>) {
            ((found = found || Is_Field<member_value_v<std::get<Is>(tp)>>()), ...);
        }(std::make_index_sequence<N>{});

        return found;
    }
};

template <IsAggregate T>
struct ReflectField<T> {
static constexpr auto reflect() {
	return ReflectHelper<T, member_count_v<T>>::reflectFieldImpl();
}
};

template <typename T>
constexpr bool reflectField_v = ReflectField<T>::reflect();

int main() {
    static_assert(!reflectField_v<Dog>);
    static_assert(reflectField_v<Person>);
    static_assert(reflectField_v<PersonPrivate>);

    constexpr auto tp = get_private_ptrs(my_wrapper<PersonPrivate>{});
    [&]<size_t... Is>(std::index_sequence<Is...>) {
        (std::cout << ... << get_member_name<std::get<Is>(tp)>());
    }(std::make_index_sequence<std::tuple_size_v<decltype(tp)>>{});
}